﻿Imports Model.Geometry
Namespace Midline
    Public Class Mid_SuperCircle
        Private _LineType As LineTypeList    '已知
        Private _startpt As Point3d                 '已知
        Private _startOri As SingleVector
        Private _startm As Double                   '已知
        Private _endpt As Point3d                   '已知
        Private _endOri As SingleVector
        Private _endm As Double                     '已知
        Private _isturnright As Boolean             '已知
        Private _length As Double                       '已知
        Private _startRadius As Double              '半径为0说明与直线相接
        Private _endRadius As Double
        Private _startoffset As Double                       '隧道中心与线路中心的偏移量
        Private _endoffset As Double

        Public Property LineType() As LineTypeList
            Get
                Return _LineType
            End Get
            Set(value As LineTypeList)
                _LineType = value
            End Set
        End Property

        Public Property startpt() As Point3d
            Get
                Return _startpt
            End Get
            Set(value As Point3d)
                _startpt = value
            End Set
        End Property

        Public Property startOri() As SingleVector
            Get
                Return _startOri
            End Get
            Set(value As SingleVector)
                _startOri = value
            End Set
        End Property

        Public Property startm() As Double
            Get
                Return _startm
            End Get
            Set(value As Double)
                _startm = value
            End Set
        End Property

        Public Property endpt() As Point3d
            Get
                Return _endpt
            End Get
            Set(value As Point3d)
                _endpt = value
            End Set
        End Property

        Public Property endOri() As SingleVector
            Get
                Return _endOri
            End Get
            Set(value As SingleVector)
                _endOri = value
            End Set
        End Property

        Public Property endm() As Double
            Get
                Return _endm
            End Get
            Set(value As Double)
                _endm = value
            End Set
        End Property

        Public Property length() As Double
            Get
                Return _length
            End Get
            Set(value As Double)
                _length = value
            End Set
        End Property

        Public Property isturnright() As Boolean
            Get
                Return _isturnright
            End Get
            Set(value As Boolean)
                _isturnright = value
            End Set
        End Property

        Public Property startRadius() As Double
            Get
                Return _startRadius
            End Get
            Set(value As Double)
                _startRadius = value
            End Set
        End Property

        Public Property endRadius() As Double
            Get
                Return _endRadius
            End Get
            Set(value As Double)
                _endRadius = value
            End Set
        End Property

        Public Property startoffset() As Double
            Get
                Return _startoffset
            End Get
            Set(value As Double)
                _startoffset = value
            End Set
        End Property

        Public Property endoffset() As Double
            Get
                Return _endoffset
            End Get
            Set(value As Double)
                _endoffset = value
            End Set
        End Property

        Public Sub New()
            LineType = LineTypeList.TypeSUPERCIRCLE
            startpt = New Point3d()
            startm = 0
            endpt = New Point3d()
            startOri = New SingleVector()
            endOri = New SingleVector()
            endm = 0
            isturnright = True
            length = 0
            startRadius = 0
            endRadius = 0
            startoffset = 0
            endoffset = 0
        End Sub
        ''' <summary>
        ''' 初始化缓和曲线各个必要参数
        ''' 求取终点方向或起点方向
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub initMyself(ByRef sob As Object)
            startOri = sob.endOri
            Dim beta As Double
            If startRadius = 0 Then
                beta = length / (2 * endRadius)
            Else
                beta = length / (2 * startRadius)
            End If
            If isturnright = True Then
                endOri.Azi = startOri.Azi + beta
            Else
                endOri.Azi = startOri.Azi - beta
            End If
            endOri.GetVector()
        End Sub
        ''' <summary>
        ''' 给定里程，在缓和曲线上求取坐标和切线向量
        ''' </summary>
        ''' <param name="mil">给定里程</param>
        ''' <param name="vec">切线向量</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetPointByMileage(ByRef mil As Double, ByVal vec As SingleVector) As Point3d
            If mil > endm Then
                Return Nothing
            End If
            Dim difmil As Double
            Dim pt, pt1 As New Point3d
            Dim dist As Double
            Dim Gamma As Double
            Dim beta As Double
            Dim cc As Integer
            Dim offset As Double
            If isturnright = True Then
                cc = 1
            Else
                cc = -1
            End If
            If startRadius = 0 Then             '直缓点-缓圆点,第一段
                difmil = mil - startm
                pt.p_x = difmil - Math.Pow(difmil, 5) / (40 * Math.Pow(endRadius * length, 2))
                pt.p_y = Math.Pow(difmil, 3) / (6 * endRadius * length) - Math.Pow(difmil, 7) / (336 * Math.Pow(endRadius * length, 3))
                If cc = 1 Then
                    pt.p_y = -1 * pt.p_y
                End If
                dist = Math.Sqrt(Math.Pow(pt.p_x, 2) + Math.Pow(pt.p_y, 2))
                Gamma = Math.Atan2(pt.p_y, pt.p_x)
                beta = difmil * difmil / (2 * endRadius * length)
                pt1.p_y = startpt.p_y + dist * Math.Cos(startOri.Azi - Gamma + 2 * Math.PI)
                pt1.p_x = startpt.p_x + dist * Math.Sin(startOri.Azi - Gamma + 2 * Math.PI)
                
                vec.Azi = startOri.Azi + cc * beta
                vec.GetVector()

                '通过偏移量计算隧道中心设计坐标
                Dim offsetAzi = vec.Azi + cc * Math.PI / 2
                offset = difmil * endoffset / length
                pt1.p_x = pt1.p_x + offset * Math.Sin(offsetAzi)
                pt1.p_y = pt1.p_y + offset * Math.Cos(offsetAzi)

            ElseIf endRadius = 0 Then       '圆缓点-缓直点,第二段
                difmil = endm - mil
                endOri.Reverse()
                'pt.p_x = difmil - Math.Pow(difmil, 5) / (40 * Math.Pow(endRadius * length, 2))
                'pt.p_y = Math.Pow(difmil, 3) / (6 * endRadius * length)
                pt.p_x = difmil - Math.Pow(difmil, 5) / (40 * Math.Pow(startRadius * length, 2))
                pt.p_y = Math.Pow(difmil, 3) / (6 * startRadius * length) - Math.Pow(difmil, 7) / (336 * Math.Pow(startRadius * length, 3))
                If cc = -1 Then
                    pt.p_y = -1 * pt.p_y
                End If
                beta = difmil * difmil / (2 * startRadius * length)
                dist = Math.Sqrt(Math.Pow(pt.p_x, 2) + Math.Pow(pt.p_y, 2))
                Gamma = Math.Atan2(pt.p_y, pt.p_x)
                pt1.p_y = endpt.p_y + dist * Math.Cos(endOri.Azi - Gamma + 2 * Math.PI)
                pt1.p_x = endpt.p_x + dist * Math.Sin(endOri.Azi - Gamma + 2 * Math.PI)
                vec.Azi = endOri.Azi - cc * beta + 2 * Math.PI
                vec.GetVector()
                vec.Reverse()

                '终点方向归位
                endOri.Reverse()

                '通过偏移量计算隧道中心设计坐标
                Dim offsetAzi = vec.Azi + cc * Math.PI / 2
                offset = difmil * startoffset / length
                pt1.p_x = pt1.p_x + offset * Math.Sin(offsetAzi)
                pt1.p_y = pt1.p_y + offset * Math.Cos(offsetAzi)

            End If
            Return pt1
        End Function
    End Class
End Namespace